<?php
require_once __DIR__ . '/vendor/autoload.php';

use Swoole\WebSocket\Server;
use Swoole\Http\Request;
use Swoole\WebSocket\Frame;
use phpseclib3\Net\SSH2;

// 错误处理
error_reporting(E_ALL);
ini_set('display_errors', 1);

echo "正在启动 WebSocket 服务器...\n";

// 创建 WebSocket 服务器
$server = new Server('127.0.0.1', 5001);

// 设置异步任务的工作进程数和日志
$server->set([
    'worker_num' => 4,
    'log_level' => SWOOLE_LOG_INFO,
    'log_file' => __DIR__ . '/swoole.log',
    'daemonize' => false,
]);

// 服务器启动时
$server->on('start', function(Server $server) {
    echo "WebSocket 服务器已启动 ws://127.0.0.1:5001\n";
    echo "进程 ID: " . posix_getpid() . "\n";
});

// Worker 进程启动时
$server->on('workerStart', function(Server $server, int $workerId) {
    echo "Worker #{$workerId} 已启动\n";
});

// WebSocket 连接建立时
$server->on('open', function(Server $server, Request $request) {
    echo "新的连接建立: {$request->fd}\n";
});

// 接收到消息时
$server->on('message', function(Server $server, Frame $frame) {
    $data = json_decode($frame->data, true);
    
    // 处理心跳
    if (isset($data['type']) && $data['type'] === 'ping') {
        $server->push($frame->fd, json_encode([
            'type' => 'pong'
        ]));
        return;
    }
    
    echo "收到消息 from {$frame->fd}: " . substr($frame->data, 0, 100) . "...\n";
    
    try {
        $params = json_decode($frame->data, true);
        if (!$params) {
            echo "参数解析失败: " . $frame->data . "\n";
            $server->push($frame->fd, json_encode([
                'type' => 'error',
                'data' => '参数错误'
            ]));
            return;
        }

        echo "解析参数成功: " . json_encode($params) . "\n";
        
        // 直接在当前进程处理，不使用异步任务
        handleSSH($server, $frame->fd, $params);
        
    } catch (Exception $e) {
        echo "消息处理错误: " . $e->getMessage() . "\n";
        $server->push($frame->fd, json_encode([
            'type' => 'error',
            'data' => "错误: " . $e->getMessage()
        ]));
    }
});

// 连接关闭时
$server->on('close', function(Server $server, int $fd) {
    echo "连接关闭: {$fd}\n";
});

// SSH 处理函数
function handleSSH($server, $fd, $params) {
    try {
        // 发送连接消息
        $server->push($fd, json_encode([
            'type' => 'message',
            'data' => "正在连接到服务器 {$params['host']}..."
        ]));

        // 构建 SSH 命令
        $sshCommand = sprintf(
            'sshpass -p %s ssh -o StrictHostKeyChecking=no %s@%s "python3 -u %s" 2>&1',
            escapeshellarg($params['password']),
            escapeshellarg($params['username']),
            escapeshellarg($params['host']),
            escapeshellarg($params['script'])
        );

        // 创建进程
        $descriptorspec = array(
            0 => array("pipe", "r"),  // stdin
            1 => array("pipe", "w"),  // stdout
            2 => array("pipe", "w")   // stderr
        );

        $process = proc_open($sshCommand, $descriptorspec, $pipes);

        if (is_resource($process)) {
            // 设置输出流为非阻塞模式
            stream_set_blocking($pipes[1], false);
            stream_set_blocking($pipes[2], false);

            $server->push($fd, json_encode([
                'type' => 'message',
                'data' => "SSH 连接已建立"
            ]));

            // 持续读取输出
            while (true) {
                $read = [$pipes[1], $pipes[2]];
                $write = null;
                $except = null;

                // 使用 select 检查是否有新数据
                if (stream_select($read, $write, $except, 0, 200000)) {
                    foreach ($read as $pipe) {
                        $data = fgets($pipe);
                        if ($data === false) {
                            continue;
                        }

                        if (trim($data) !== '') {
                            // 过滤掉终端控制字符
                            $data = preg_replace('/\x1b(\[|\])[;?0-9]*[a-zA-Z]/', '', $data);
                            
                            $server->push($fd, json_encode([
                                'type' => 'message',
                                'data' => trim($data)
                            ]));
                        }
                    }
                }

                // 检查进程是否结束
                $status = proc_get_status($process);
                if (!$status['running']) {
                    break;
                }

                // 短暂休眠，避免 CPU 占用过高
                usleep(50000); // 50ms
            }

            // 关闭所有管道
            fclose($pipes[0]);
            fclose($pipes[1]);
            fclose($pipes[2]);

            // 关闭进程
            proc_close($process);

            $server->push($fd, json_encode([
                'type' => 'message',
                'data' => "脚本执行完毕"
            ]));
        }

    } catch (Exception $e) {
        $server->push($fd, json_encode([
            'type' => 'error',
            'data' => "错误: " . $e->getMessage()
        ]));
    }
}

echo "正在启动服务器...\n";
$server->start(); 